package com.jieclouds.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class DjZhiTu {
    public static final String URI_TOKEN = "/terra-rescon-be/v2/store/obtain_token";
    private static final String ENDPOINT = "https://oss-cn-hangzhou.aliyuncs.com";

    public static final String RESOURE_PATH = "/terra-rescon-be/v2/resources";
    public static final String URI_ASSOCIATE_FILE = "/terra-rescon-be/v2/store/upload_callback";
    public static final String CREAT_JOB_PATH = "/terra-rescon-be/v2/jobs";

    //我的本地素材地址
    private static final String FILE_PATH = "D:\\dj3D\\20241023image";

    public static void main(String[] args) throws IOException, InterruptedException {
        start();
    }

    public static void start() throws IOException {
        //1. 获取token
        System.out.println("获取token");
        JSONObject accessToken = getAccessToken();
        JSONObject dataToken = JSONUtil.parseObj(accessToken.get("data"));
        Object callbackParam = dataToken.get("callbackParam");
        String storePath = (String) dataToken.get("storePath");
        storePath=storePath.substring(0,storePath.length()-10);

        //将本地素材上传到大疆oss
        boolean isSuccess = uploadFile(ENDPOINT, (String) dataToken.get("accessKeyID"), (String) dataToken.get("secretAccessKey"), (String) dataToken.get("cloudBucketName"),
                storePath, (String) dataToken.get("sessionToken"),FILE_PATH);
        if (isSuccess){
            //2. 创建resoure
            System.out.println("创建resoure");
            JSONObject resource = creatRescoure();
            JSONObject resourceData = JSONUtil.parseObj(resource.get("data"));
            String rescoureUuid = resourceData.getStr("uuid");
            //3. 关联文件
            System.out.println("关联文件");
            associateFile(rescoureUuid,callbackParam);
            //4. 创建job
            JSONObject job = creatJob();
            JSONObject jobData = job.getJSONObject("data");
            String jobUuid = jobData.getStr("uuid");

            //启动3Djob
            start3DJob(rescoureUuid,jobUuid);
            while (true) {
                //作业状态，0:待开始，1:等待中，2:准备中，3:执行中，4:处理结果中，5:已停止，6:执行完成，7:执行失败
                JSONObject jobStatus = getJobStatus(jobUuid);
                JSONObject result = jobStatus.getJSONObject("result");
                JSONObject data = jobStatus.getJSONObject("data");
                log.info("job状态：" + data.getInt("status"));
                if (result.getInt("code") == 0 && data.getInt("status") == 6) {
                    jobSuccessDownloadFile(data.getStr("outputResourceUuid"));
                    break;
                }
                try {
                    Thread.sleep(1000*60*1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }else {
            log.error("上传文件失败");
        }
    }

    public static void jobSuccessDownloadFile(String outputResourceUuid){
        //工作成功后下载文件
        String downurl="/terra-rescon-be/v2/resources/"+outputResourceUuid;//
        JSONObject jsonObject = DjApi.AccessDJ(downurl, "", "get");
        //获取
        List<String> fileUuids = (List<String>) JSONUtil.parseObj(jsonObject.get("data")).get("fileUuids");
        for (String fileUuid :fileUuids
        ) {
            String uri="/terra-rescon-be/v2/files/"+fileUuid;
            JSONObject fileUuidJSON = DjApi.AccessDJ(uri, "", "get");//获取文件信息Json
            String url = (String) JSONUtil.parseObj(fileUuidJSON.get("data")).get("url");
            // 使用HttpRequest获取文件
            HttpResponse response = HttpRequest.get(url)
                    .timeout(20000) // 设置超时时间
                    .execute();
//            String savePath = "/file/"+JSONUtil.parseObj(fileUuidJSON.get("data")).get("name");//如果项目在D盘 则保存路径为D:/file/xxx.xxx
            String savePath = "D:/file/"+JSONUtil.parseObj(fileUuidJSON.get("data")).get("name");//如果项目在D盘 则保存路径为D:/file/xxx.xxx
            // 判断响应状态码是否为200
            if (response.isOk()) {
                // 读取响应体到字节数组
                byte[] bytes = response.bodyBytes();
                // 将字节数组写入文件
                FileUtil.writeBytes(bytes, savePath);
                System.out.println("文件下载成功，保存路径：" + savePath);
            } else {
                System.out.println("文件下载失败，状态码：" + response.getStatus());
            }
        }
    }


    /**
     * 获取token
     * @return
     */
    public static JSONObject getAccessToken() {
        return DjApi.AccessDJ(URI_TOKEN, "","post");
    }

    /**
     * 上传素材
     * ENDPOINT 大疆智图API的外网访问网址 默认 https://oss-cn-hangzhou.aliyuncs.com
     *        ACCESS_KEY_ID  token的 accessKeyID
     *        SECRET_ACCESS_KEY  token的 secretAccessKey
     *        BUCKET_NAME  token的 cloudBucketName
     *        STORE_PATH  token的 sessionToken
     *        TOKEN  token的 sessionToken
     *        FILE_PATH  本地素材的路径
    */
    public static boolean uploadFile(String ENDPOINT, String ACCESS_KEY_ID, String SECRET_ACCESS_KEY, String BUCKET_NAME, String STORE_PATH, String TOKEN,String FILE_PATH) throws IOException {
        boolean success = false;
        OSS ossClient = new OSSClientBuilder().build(ENDPOINT,ACCESS_KEY_ID,SECRET_ACCESS_KEY,TOKEN);
        List<Map<String, String>> uploadedFiles = new ArrayList<>();

        File localFolder = new File(FILE_PATH);
        Files.walk(localFolder.toPath())
                .filter(Files::isRegularFile)
                .forEach(path -> {
                    String relativePath = localFolder.toURI().relativize(path.toUri()).getPath();
                    String ossFilePath = STORE_PATH + relativePath.replace("\\", "/");
                    try {
                        PutObjectResult putResult = ossClient.putObject(BUCKET_NAME, ossFilePath, path.toFile());
                        String etag = putResult.getETag();
                        System.out.println("Uploaded: " + path + " -> " + ossFilePath + ", etag: " + etag);

                        Map<String, String> fileInfo = new HashMap<>();
                        fileInfo.put("name", relativePath.replace("\\", "/"));
                        fileInfo.put("etag", etag);
                        fileInfo.put("checksum", etag);
                        uploadedFiles.add(fileInfo);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });

        if (!uploadedFiles.isEmpty()) {
            String json = JSONUtil.toJsonStr(uploadedFiles);
            // 将JSON字符串写入文件
            try {
                Files.writeString(Paths.get("uploaded_files.json"), json);
                System.out.println("文件写入成功！");
                success = true;
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("文件写入失败！");
            }
        }
        ossClient.shutdown();
        return success;
    }

    /**
     * 将本地素材上传到大疆oss
     * @return
     * @throws IOException
     */
    public static boolean isSuccessUPload() throws IOException {
        //获取token
        JSONObject accessToken = DjApi.AccessDJ(URI_TOKEN, "", "post");
        JSONObject dataToken = JSONUtil.parseObj(accessToken.get("data"));
        String storePath = (String) dataToken.get("storePath");
        //获取的storePath多了{fileName} 需要去掉
        storePath=storePath.substring(0,storePath.length()-10);
        //将本地素材上传到大疆oss
        return uploadFile(ENDPOINT, (String) dataToken.get("accessKeyID"), (String) dataToken.get("secretAccessKey"), (String) dataToken.get("cloudBucketName"),
                storePath, (String) dataToken.get("sessionToken"),FILE_PATH);
    }

    /**
     * 创建resoure
     * @return
     */
    public static JSONObject creatRescoure(){
        //payload 设置参数 参考API文档  name: resource名称 type: 类型
        String payload="{\"name\": \"202410211301\", \"type\": \"map\"}";
        return DjApi.AccessDJ(RESOURE_PATH,payload ,"post");
    }

    /**
     * 关联文件
     * @param resource_uuid
     * @param callbackParam
     * @return
     * @throws IOException
     */
    public static JSONObject associateFile(Object resource_uuid, Object callbackParam) throws IOException {
        String filesJson = Files.readString(Paths.get("uploaded_files.json"));
        JSONArray filesArray = JSONUtil.parseArray(filesJson);
        List<JSONObject> payloadJson = new ArrayList<>();
        int a=0;
        String payload="";
        for (int i = 0; i < filesArray.size(); i++) {
            payloadJson.add((JSONObject) filesArray.get(i));
            a++;
            if(a>=50){
                payload = JSONUtil.toJsonStr(Map.of("resourceUUID", resource_uuid, "callbackParam", callbackParam, "files", payloadJson));
                DjApi.AccessDJ(URI_ASSOCIATE_FILE,payload , "post");
                a=0;
                payloadJson.clear();
            }
        }
        return DjApi.AccessDJ(URI_ASSOCIATE_FILE,payload , "post");
    }

    /**
     * 创建Job
     * @return
     */
    public static JSONObject creatJob(){
        log.info("创建job");
        //payload 设置参数 参考API文档  name: job名称
        String payload="{\"name\": \"202410211410\"}";
        return DjApi.AccessDJ(CREAT_JOB_PATH,payload ,"post");
    }

    /**
     * 启动 3D 类型 job
     * @return
     */
    public static JSONObject start3DJob(String resource_uuid,String job_uuid){
        log.info("启动job");
        String url="/terra-rescon-be/v2/jobs/"+job_uuid+"/start";
        JSONObject payload = new JSONObject();
        payload.set("type",15).set("resourceUUID",resource_uuid).set("parameters",
                "{\"parameter\":{\"output_mesh\": true,\"generate_obj\": true,\"generate_b3dm\": true,\"generate_osgb\": true}}");
        return DjApi.AccessDJ(url, payload.toString(), "post");
    }

    /**
     * 查询job状态
     * @return
     */
    public static JSONObject getJobStatus(String jobUuid){
        String url="/terra-rescon-be/v2/jobs/"+jobUuid;
        log.info("查询job状态");
        return DjApi.AccessDJ(url, "", "get");
    }




}
